﻿#include "GuildObject.h"
#include "../../Shared/ServerPackets.h"
#include "../Settings.h"
#include "MapObject.h"
#include "../MirDatabase/CharacterInfo.h"

using namespace Server::MirEnvir;

namespace Server::MirObjects
{

    Server::MirEnvir::Envir *GuildObject::getEnvir()
    {
        return Envir::getMain();
    }

    GuildObject::GuildObject()
    {
    }

    GuildObject::GuildObject(PlayerObject *owner, const std::string &name)
    {
        Name = name;
        GuildRank *Owner = new GuildRank();
        Owner->Name = "Leader";
        Owner->Options = static_cast<GuildRankOptions>(255);
        Owner->Index = 0;
        GuildMember *Leader = new GuildMember();
        Leader->name = owner->Info->Name;
        Leader->Player = owner;
        Leader->Id = owner->Info->Index;
        Leader->LastLogin = getEnvir()->getNow();
        Leader->Online = true;
        Owner->Members.push_back(Leader);
        Ranks.push_back(Owner);
        Membercount++;
        NeedSave = true;
        if (Level < Settings::Guild_ExperienceList.size())
        {
            MaxExperience = Settings::Guild_ExperienceList[Level];
        }
        if (Level < Settings::Guild_MembercapList.size())
        {
            MemberCap = Settings::Guild_MembercapList[Level];
        }

        FlagColour = Color::FromArgb(255, getEnvir()->Random->Next(255), getEnvir()->Random->Next(255), getEnvir()->Random->Next(255));

//C# TO C++ CONVERTER TODO TASK: A 'delete Leader' statement was not added since Leader was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete Owner' statement was not added since Owner was passed to a method or constructor. Handle memory management manually.
    }

    GuildObject::GuildObject(BinaryReader *reader)
    {
        int customversion = Envir::LoadCustomVersion;
        int version = reader->ReadInt32();
        Guildindex = version;
        if (version == std::numeric_limits<int>::max())
        {
            version = reader->ReadInt32();
            customversion = reader->ReadInt32();
            Guildindex = reader->ReadInt32();
        }
        else
        {
            version = Envir::LoadVersion;
            NeedSave = true;
        }
        Name = reader->ReadString();
        Level = reader->ReadByte();
        SparePoints = reader->ReadByte();
        Experience = reader->ReadInt64();
        Gold = reader->ReadUInt32();
        Votes = reader->ReadInt32();
        LastVoteAttempt = DateTime::FromBinary(reader->ReadInt64());
        Voting = reader->ReadBoolean();
        int RankCount = reader->ReadInt32();
        Membercount = 0;
        for (int i = 0; i < RankCount; i++)
        {
            int index = i;
            GuildRank *tempVar = new GuildRank(reader, true);
            tempVar->Index = index;
            Ranks.push_back(tempVar);
            Membercount += Ranks[i]->Members->size();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
        }
        int ItemCount = reader->ReadInt32();
        for (int j = 0; j < ItemCount; j++)
        {
            if (!reader->ReadBoolean())
            {
                continue;
            }

            GuildStorageItem *Guilditem = new GuildStorageItem();
            Guilditem->Item = new UserItem(reader, version, customversion);
            Guilditem->UserId = reader->ReadInt64();

            if (getEnvir()->BindItem(Guilditem->Item) && j < StoredItems.size())
            {
                StoredItems[j] = Guilditem;
            }

            delete Guilditem;
        }
        int BuffCount = reader->ReadInt32();
        if (version < 61)
        {
            for (int j = 0; j < BuffCount; j++)
            {
                new GuildBuffOld(reader);
            }
        }
        else
        {
            for (int j = 0; j < BuffCount; j++)
            {
                //new GuildBuff(reader);
                GuildBuff tempVar2(reader);
                BuffList.push_back(&tempVar2);
            }
        }
        for (int j = 0; j < BuffList.size(); j++)
        {
            BuffList[j]->Info = getEnvir()->FindGuildBuffInfo(BuffList[j]->Id);
        }
        int NoticeCount = reader->ReadInt32();
        for (int j = 0; j < NoticeCount; j++)
        {
            Notice.push_back(reader->ReadString());
        }
        if (Level < Settings::Guild_ExperienceList.size())
        {
            MaxExperience = Settings::Guild_ExperienceList[Level];
        }
        if (Level < Settings::Guild_MembercapList.size())
        {
            MemberCap = Settings::Guild_MembercapList[Level];
        }

        if (version > 72)
        {
            FlagImage = reader->ReadUInt16();
            FlagColour = Color::FromArgb(reader->ReadInt32());
        }
    }

    void GuildObject::Save(BinaryWriter *writer)
    {
        int temp = std::numeric_limits<int>::max();
        writer->Write(temp);
        writer->Write(getEnvir()->Version);
        writer->Write(getEnvir()->CustomVersion);

        int RankCount = 0;
        for (int i = Ranks.size() - 1; i >= 0; i--)
        {
            if (Ranks[i]->Members->size() > 0)
            {
                RankCount++;
            }
        }

        writer->Write(Guildindex);
        writer->Write(Name);
        writer->Write(Level);
        writer->Write(SparePoints);
        writer->Write(Experience);
        writer->Write(Gold);
        writer->Write(Votes);
        writer->Write(LastVoteAttempt.ToBinary());
        writer->Write(Voting);
        writer->Write(RankCount);
        for (int i = 0; i < Ranks.size(); i++)
        {
            if (Ranks[i]->Members->size() > 0)
            {
                Ranks[i]->Save(writer,true);
            }
        }
        writer->Write(StoredItems.size());
        for (int i = 0; i < StoredItems.size(); i++)
        {
            writer->Write(StoredItems[i] != nullptr);
            if (StoredItems[i] != nullptr)
            {
                StoredItems[i]->Item->Save(writer);
                writer->Write(StoredItems[i]->UserId);
            }
        }
        writer->Write(BuffList.size());
        for (int i = 0; i < BuffList.size(); i++)
        {
            BuffList[i]->Save(writer);
        }
        writer->Write(Notice.size());
        for (int i = 0; i < Notice.size(); i++)
        {
            writer->Write(Notice[i]);
        }

        writer->Write(FlagImage);
        writer->Write(FlagColour->ToArgb());
    }

    void GuildObject::SendMessage(const std::string &message, ChatType Type)
    {
        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                PlayerObject *player = std::any_cast<PlayerObject*>(Ranks[i]->Members[j].Player);
                if (player != nullptr)
                {
                    player->ReceiveChat(message, Type);
                }
            }
        }
    }

    void GuildObject::SendOutputMessage(const std::string &message, OutputMessageType Type)
    {
        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                PlayerObject *player = std::any_cast<PlayerObject*>(Ranks[i]->Members[j].Player);
                if (player != nullptr)
                {
                    player->ReceiveOutputMessage(message, Type);
                }
            }
        }
    }

    std::vector<PlayerObject*> GuildObject::GetOnlinePlayers()
    {
        std::vector<PlayerObject*> players;

        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                PlayerObject *player = std::any_cast<PlayerObject*>(Ranks[i]->Members[j].Player);
                if (player != nullptr)
                {
                    players.push_back(player);
                }
            }
        }

        return players;
    }

    void GuildObject::PlayerLogged(PlayerObject *member, bool online, bool New)
    {
        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                if (Ranks[i]->Members[j]->Id == member->Info->Index)
                {
                    if (online)
                    {
                        Ranks[i]->Members[j]->Player = member;
                        Ranks[i]->Members[j]->Online = true;
                    }
                    else
                    {
                        Ranks[i]->Members[j]->LastLogin = getEnvir()->getNow();
                        Ranks[i]->Members[j]->Player = std::any();
                        Ranks[i]->Members[j]->Online = false;
                        NeedSave = true;
                    }
                }
            }
        }
        ServerPackets::GuildMemberChange *tempVar = new ServerPackets::GuildMemberChange();
        tempVar->Name = member->getName();
        tempVar->Status = static_cast<unsigned char>(New? 2: online? 1: 0);
        SendServerPacket(tempVar);
        if (online && !New)
        {
            SendGuildStatus(member);
        }

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void GuildObject::SendGuildStatus(PlayerObject *member)
    {
        std::string gName = Name;
        if (Conquest != nullptr)
        {
            std::string conquest = "[" + Conquest->Info->Name + "]";
            gName += conquest;
        }

        ServerPackets::GuildStatus *tempVar = new ServerPackets::GuildStatus();
        tempVar->GuildName = gName;
        tempVar->GuildRankName = member->MyGuildRank != nullptr? member->MyGuildRank->Name: "";
        tempVar->Experience = Experience;
        tempVar->MaxExperience = MaxExperience;
        tempVar->MemberCount = Membercount;
        tempVar->MaxMembers = MemberCap;
        tempVar->Gold = Gold;
        tempVar->Level = Level;
        tempVar->Voting = Voting;
        tempVar->SparePoints = SparePoints;
        tempVar->ItemCount = static_cast<unsigned char>(StoredItems.size());
        tempVar->BuffCount = static_cast<unsigned char>(0);
        tempVar->MyOptions = member->MyGuildRank != nullptr? member->MyGuildRank->Options: static_cast<GuildRankOptions>(0);
        tempVar->MyRankId = member->MyGuildRank != nullptr? member->MyGuildRank->Index: 256;
        member->Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void GuildObject::NewMember(PlayerObject *newMember)
    {
        if (Ranks.size() < 2)
        {
            GuildRank *tempVar = new GuildRank();
            tempVar->Name = "Members";
            tempVar->Index = 1;
            Ranks.push_back(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
        }
        GuildRank *currentrank = Ranks[Ranks.size() - 1];
        GuildMember *Member = new GuildMember();
        Member->name = newMember->Info->Name;
        Member->Player = newMember;
        Member->Id = newMember->Info->Index;
        Member->LastLogin = getEnvir()->getNow();
        Member->Online = true;
        currentrank->Members.push_back(Member);
        PlayerLogged(newMember, true, true);
        Membercount++;
        NeedSave = true;

//C# TO C++ CONVERTER TODO TASK: A 'delete Member' statement was not added since Member was passed to a method or constructor. Handle memory management manually.
    }

    bool GuildObject::ChangeRank(PlayerObject *self, const std::string &memberName, unsigned char rankIndex, const std::string &rankName)
    {
        if ((self->MyGuild != this) || (self->MyGuildRank == nullptr))
        {
            return false;
        }
        if (rankIndex >= Ranks.size())
        {
            return false;
        }
        GuildMember *Member = nullptr;
        GuildRank *MemberRank = nullptr;
        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                if (Ranks[i]->Members[j]->name == memberName)
                {
                    Member = Ranks[i]->Members[j];
                    MemberRank = Ranks[i];
                    goto Found;
                }
            }
        }

        Found:
        if (Member == nullptr)
        {
            return false;
        }

        MirDatabase::CharacterInfo *Character = getEnvir()->GetCharacterInfo(memberName);
        if (Character == nullptr)
        {
            return false;
        }
        if ((rankIndex == 0) && (Character->Level < Settings::Guild_RequiredLevel))
        {
            self->ReceiveChat(StringHelper::formatSimple("A guild leader needs to be at least level {0}", Settings::Guild_RequiredLevel), ChatType::System);
            return false;
        }

        if ((MemberRank->Index >= self->MyGuildRank->Index) && (self->MyGuildRank->Index != 0))
        {
            return false;
        }
        if (MemberRank->Index == 0)
        {
            if (MemberRank->Members.size() <= 2)
            {
                self->ReceiveChat("A guild needs at least 2 leaders.", ChatType::System);
                return false;
            }
            for (int i = 0; i < MemberRank->Members.size(); i++)
            {
                if ((MemberRank->Members[i]->Player.has_value()) && (MemberRank->Members[i] != Member))
                {
                    goto AllOk;
                }
            }
            self->ReceiveChat("You need at least 1 leader online.", ChatType::System);
            return false;
        }

        AllOk:
        Ranks[rankIndex]->Members->push_back(Member);
        MemberRank->Members.Remove(Member);

        MemberRank = Ranks[rankIndex];

        std::vector<GuildRank*> NewRankList = std::vector<std::vector<GuildRank*>>(rankIndex) };
        NeedSave = true;
        PlayerObject *player = std::any_cast<PlayerObject*>(Member->Player);
        if (player != nullptr)
        {
            player->MyGuildRank = Ranks[rankIndex];
            ServerPackets::GuildMemberChange *tempVar = new ServerPackets::GuildMemberChange();
            tempVar->Name = self->Info->Name;
            tempVar->Status = static_cast<unsigned char>(8);
            tempVar->Ranks = NewRankList;
            player->Enqueue(tempVar);
            player->BroadcastInfo();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
        }

        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                if ((Ranks[i]->Members[j].Player.has_value()) && (Ranks[i]->Members[j].Player != Member->Player))
                {
                    player = std::any_cast<PlayerObject*>(Ranks[i]->Members[j].Player);
                    ServerPackets::GuildMemberChange *tempVar2 = new ServerPackets::GuildMemberChange();
                    tempVar2->Name = Member->name;
                    tempVar2->Status = static_cast<unsigned char>(5);
                    tempVar2->RankIndex = static_cast<unsigned char>(MemberRank->Index);
                    player->Enqueue(tempVar2);
                    player->GuildMembersChanged = true;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
                }
            }
        }
        return true;
    }

    bool GuildObject::NewRank(PlayerObject *Self)
    {
        if (Ranks.size() >= std::numeric_limits<unsigned char>::max())
        {
            Self->ReceiveChat("You cannot have anymore ranks.", ChatType::System);
            return false;
        }
        int NewIndex = Ranks.size() > 1? Ranks.size() - 1: 1;
        GuildRank *NewRank = new GuildRank();
        NewRank->Index = NewIndex;
        NewRank->Name = StringHelper::formatSimple("Rank-{0}",NewIndex);
        NewRank->Options = static_cast<GuildRankOptions>(0);
        Ranks.Insert(NewIndex, NewRank);
        Ranks[Ranks.size() - 1]->Index = Ranks.size() - 1;
        std::vector<GuildRank*> NewRankList = {NewRank};
        ServerPackets::GuildMemberChange *tempVar = new ServerPackets::GuildMemberChange();
        tempVar->Name = Self->getName();
        tempVar->Status = static_cast<unsigned char>(6);
        tempVar->Ranks = NewRankList;
        SendServerPacket(tempVar);
        NeedSave = true;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete NewRank' statement was not added since NewRank was passed to a method or constructor. Handle memory management manually.
        return true;
    }

    bool GuildObject::ChangeRankOption(PlayerObject *Self, unsigned char RankIndex, int Option, const std::string &Enabled)
    {
        if ((RankIndex >= Ranks.size()) || (Option > 7))
        {
            Self->ReceiveChat("Rank not found!", ChatType::System);
            return false;
        }
        if (Self->MyGuildRank->Index >= RankIndex)
        {
            Self->ReceiveChat("You cannot change the options of your own rank!", ChatType::System);
            return false;
        }
        if ((Enabled != "true") && (Enabled != "false"))
        {
            return false;
        }
        Ranks[RankIndex]->Options = Enabled == "true" ? Ranks[RankIndex]->Options |= static_cast<GuildRankOptions>(1 << Option) : Ranks[RankIndex]->Options ^= static_cast<GuildRankOptions>(1 << Option);

        std::vector<GuildRank*> NewRankList = std::vector<std::vector<GuildRank*>>(RankIndex) };
        ServerPackets::GuildMemberChange *tempVar = new ServerPackets::GuildMemberChange();
        tempVar->Name = Self->getName();
        tempVar->Status = static_cast<unsigned char>(7);
        tempVar->Ranks = NewRankList;
        SendServerPacket(tempVar);
        NeedSave = true;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
        return true;
    }

    bool GuildObject::ChangeRankName(PlayerObject *Self, const std::string &RankName, unsigned char RankIndex)
    {
        int SelfRankIndex = -1;
        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                if (obj::type() == typeid(Server::MirObjects::PlayerObject) && std::any_cast<Server::MirObjects::PlayerObject>(obj) == Self)
                {
                    SelfRankIndex = i;
                    break;
                }
            }
        }

        if (SelfRankIndex > RankIndex)
        {
            Self->ReceiveChat("Your rank is not adequate.", ChatType::System);
            return false;
        }
        if (RankIndex >= Ranks.size())
        {
            return false;
        }
        Ranks[RankIndex]->Name = RankName;
        std::vector<GuildRank*> NewRankList = std::vector<std::vector<GuildRank*>>(RankIndex) };
        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                PlayerObject *player = std::any_cast<PlayerObject*>(Ranks[i]->Members[j].Player);
                if (player != nullptr)
                {
                    ServerPackets::GuildMemberChange *tempVar = new ServerPackets::GuildMemberChange();
                    tempVar->Name = Self->Info->Name;
                    tempVar->Status = static_cast<unsigned char>(7);
                    tempVar->Ranks = NewRankList;
                    player->Enqueue(tempVar);
                    player->GuildMembersChanged = true;
                    if (i == RankIndex)
                    {
                        player->BroadcastInfo();
                    }

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
                }
            }
        }
        NeedSave = true;
        return true;
    }

    bool GuildObject::DeleteMember(PlayerObject *Kicker, const std::string &membername)
    { //carefull this can lead to guild with no ranks or members(or no leader)

        GuildMember *Member = nullptr;
        GuildRank *MemberRank = nullptr;
        if ((Kicker->MyGuild != this) || (Kicker->MyGuildRank == nullptr))
        {
            return false;
        }
        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                if (Ranks[i]->Members[j]->name == membername)
                {
                    Member = Ranks[i]->Members[j];
                    MemberRank = Ranks[i];
                    goto Found;
                }
            }
        }

        Found:
        if (Member == nullptr)
        {
            return false;
        }
        if (((Kicker->MyGuildRank->Index >= MemberRank->Index) && (Kicker->MyGuildRank->Index != 0)) && (Kicker->Info->Name != membername))
        {
            Kicker->ReceiveChat("Your rank is not adequate.", ChatType::System);
            return false;
        }
        if (MemberRank->Index == 0)
        {
            if (MemberRank->Members.size() < 2)
            {
                Kicker->ReceiveChat("You cannot leave the guild when you're leader.", ChatType::System);
                return false;
            }
            for (int i = 0; i < MemberRank->Members.size(); i++)
            {
                if ((MemberRank->Members[i]->Online) && (MemberRank->Members[i] != Member))
                {
                    goto AllOk;
                }
            }
            Kicker->ReceiveChat("You need at least 1 leader online.", ChatType::System);
            return false;
        }
        AllOk:
        MemberDeleted(membername, std::any_cast<PlayerObject*>(Member->Player), Member->name == Kicker->Info->Name);
        if (Member->Player.has_value())
        {
            PlayerObject *LeavingMember = std::any_cast<PlayerObject*>(Member->Player);
            LeavingMember->RefreshStats();
        }
        MemberRank->Members.Remove(Member);
        NeedSave = true;
        Membercount--;
        return true;
    }

    void GuildObject::MemberDeleted(const std::string &name, PlayerObject *formerMember, bool kickSelf)
    {
        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                if ((Ranks[i]->Members[j].Player.has_value()) && (obj::type() != typeid(Server::MirObjects::PlayerObject) || std::any_cast<Server::MirObjects::PlayerObject>(obj) != formerMember))
                {
                    PlayerObject *player = std::any_cast<PlayerObject*>(Ranks[i]->Members[j].Player);
                    ServerPackets::GuildMemberChange *tempVar = new ServerPackets::GuildMemberChange();
                    tempVar->Name = name;
                    tempVar->Status = static_cast<unsigned char>(kickSelf ? 4:3);
                    player->Enqueue(tempVar);
                    player->GuildMembersChanged = true;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
                }
            }
        }
        if (formerMember != nullptr)
        {
            formerMember->Info->GuildIndex = -1;
            formerMember->MyGuild = nullptr;
            formerMember->MyGuildRank = nullptr;
            formerMember->ReceiveChat(kickSelf ? "You have left your guild." : "You have been removed from your guild.", ChatType::Guild);
            formerMember->RefreshStats();
            ServerPackets::GuildStatus *tempVar2 = new ServerPackets::GuildStatus();
            tempVar2->GuildName = "";
            tempVar2->GuildRankName = "";
            tempVar2->MyOptions = static_cast<GuildRankOptions>(0);
            formerMember->Enqueue(tempVar2);
            formerMember->BroadcastInfo();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
        }
    }

    GuildRank *GuildObject::FindRank(const std::string &name)
    {
        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                if (Ranks[i]->Members[j]->name == name)
                {
                    return Ranks[i];
                }
            }
        }
        return nullptr;
    }

    void GuildObject::NewNotice(std::vector<std::string> &notice)
    {
        Notice = notice;
        NeedSave = true;
        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                if (Ranks[i]->Members[j].Player.has_value())
                {
                    PlayerObject *player = std::any_cast<PlayerObject*>(Ranks[i]->Members[j].Player);
                    player->GuildNoticeChanged = true;
                }
            }
        }
        ServerPackets::GuildNoticeChange *tempVar = new ServerPackets::GuildNoticeChange();
        tempVar->update = -1;
        SendServerPacket(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void GuildObject::SendServerPacket(Packet *p)
    {
        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                PlayerObject *player = std::any_cast<PlayerObject*>(Ranks[i]->Members[j].Player);
                if (player != nullptr)
                {
                    player->Enqueue(p);
                }
            }
        }
    }

    void GuildObject::SendItemInfo(UserItem *Item)
    {
        for (int i = 0; i < Ranks.size(); i++)
        {
            for (int j = 0; j < Ranks[i]->Members->size(); j++)
            {
                PlayerObject *player = std::any_cast<PlayerObject*>(Ranks[i]->Members[j].Player);
                if (player != nullptr)
                {
                    player->CheckItem(Item);
                }
            }
        }
    }

    bool GuildObject::HasRoom()
    {
        if (Level < Settings::Guild_MembercapList.size())
        {
            if ((Settings::Guild_MembercapList[Level] != 0) && (Membercount >= Settings::Guild_MembercapList[Level]))
            {
                return false;
            }
        }

        return true;
    }

    void GuildObject::GainExp(unsigned int amount)
    {
        bool Leveled = false;
        if (MaxExperience == 0)
        {
            return;
        }
        unsigned int ExpAmount = static_cast<unsigned int>(amount * Settings::Guild_ExpRate);
        if (ExpAmount == 0)
        {
            return;
        }
        Experience += ExpAmount;

        auto experience = Experience;

        while (experience > MaxExperience)
        {
            Leveled = true;
            Level++;
            SparePoints = static_cast<unsigned char>(std::min(std::numeric_limits<unsigned char>::max(), SparePoints + Settings::Guild_PointPerLevel));
            experience -= MaxExperience;
            if (Level < Settings::Guild_ExperienceList.size())
            {
                MaxExperience = Settings::Guild_ExperienceList[Level];
            }
            else
            {
                MaxExperience = 0;
            }
            if (MaxExperience == 0)
            {
                break;
            }
            if (Level == std::numeric_limits<unsigned char>::max())
            {
                break;
            }
        }

        if (Leveled)
        {
            if (Level < Settings::Guild_MembercapList.size())
            {
                MemberCap = Settings::Guild_MembercapList[Level];
            }
            NextExpUpdate = getEnvir()->getTime() + 10000;
            for (int i = 0; i < Ranks.size(); i++)
            {
                for (int j = 0; j < Ranks[i]->Members->size(); j++)
                {
                    if (Ranks[i]->Members[j].Player.has_value())
                    {
                        SendGuildStatus(std::any_cast<PlayerObject*>(Ranks[i]->Members[j].Player));
                    }
                }
            }
        }
        else
        {
            if (NextExpUpdate < getEnvir()->getTime())
            {
                NextExpUpdate = getEnvir()->getTime() + 10000;
                ServerPackets::GuildExpGain *tempVar = new ServerPackets::GuildExpGain();
                tempVar->Amount = ExpAmount;
                SendServerPacket(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            }
        }

    }

    bool GuildObject::GoToWar(GuildObject *enemyGuild)
    {
        if (enemyGuild == nullptr)
        {
            return false;
        }

        if (getEnvir()->GuildsAtWar.Where([&] (std::any e)
        {
            return e->GuildA == this && e->GuildB == enemyGuild;
        }).Any() || getEnvir()->GuildsAtWar.Where([&] (std::any e)
        {
            return e->GuildA == enemyGuild && e->GuildB == this;
        }).Any()){return false;
        {
        }
    }

    void <missing_class_definition>::UpdatePlayersColours()
    {
        for (int i = 0; i < Ranks->Count; i++)
        {
            for (int j = 0; j < Ranks[i].Members->Count; j++)
            {
                //in a way this is a horrible spam situation, it should only broadcast to your  own guild or enemy or allies guild but not sure i wanna code yet another broadcast for that
                PlayerObject *player = static_cast<PlayerObject*>(Ranks[i].Members[j].Player);
                if (player != nullptr)
                {
                    //player.Enqueue(player.GetInfoEx(player));
                    ServerPackets::ColourChanged *tempVar = new ServerPackets::ColourChanged();
                    tempVar->NameColour = player->GetNameColour(player);
                    player->Enqueue(tempVar);
                    player->BroadcastInfo();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
                }
            }
        }
    }

    bool <missing_class_definition>::IsAtWar()
    {
        if (WarringGuilds->Count == 0)
        {
            return false;
        }
        return true;
    }

    std::string <missing_class_definition>::GetName()
    {
        if (Conquest != nullptr)
        {
            return Name + "[" + Conquest::Info->Name + "]";
        }
        else
        {
            return Name;
        }
    }

    bool <missing_class_definition>::IsEnemy(GuildObject *enemyGuild)
    {
        if (enemyGuild == nullptr)
        {
            return false;
        }
        if (enemyGuild->IsAtWar() != true)
        {
            return false;
        }
        for (int i = 0; i < WarringGuilds->Count; i++)
        {
            if (WarringGuilds[i] == enemyGuild)
            {
                return true;
            }
        }
        return false;
    }

    void <missing_class_definition>::RefreshAllStats()
    {
        for (int i = 0; i < Ranks->Count; i++)
        {
            for (int j = 0; j < Ranks[i].Members->Count; j++)
            {
                PlayerObject *player = static_cast<PlayerObject*>(Ranks[i].Members[j].Player);
                if (player != nullptr)
                {
                    player->RefreshStats();
                }
            }
        }
    }

    void <missing_class_definition>::Process()
    {
        //guild buffs
        bool NeedUpdate = false;
        std::vector<GuildBuff*> UpdatedBuffs;
        for (int k = 0; k < BuffList->Count; k++)
        {
            if ((BuffList[k]->Info == nullptr) || (BuffList[k].Info->TimeLimit == 0))
            {
                continue; //dont bother if it's infinite buffs
            }
            if (BuffList[k]->Active == false)
            {
                continue; //dont bother if the buff isnt active
            }
            BuffList[k].ActiveTimeRemaining -= 1;
            if (BuffList[k].ActiveTimeRemaining < 0)
            {
                NeedUpdate = true;
                BuffList[k]->Active = false;
                UpdatedBuffs.push_back(BuffList[k]);
                //SendServerPacket(new ServerPackets.RemoveGuildBuff {ObjectID = (uint)BuffList[k].Id});
            }
        }
        if (NeedUpdate)
        {
            if (UpdatedBuffs.size() > 0)
            {
                ServerPackets::GuildBuffList *tempVar = new ServerPackets::GuildBuffList();
                tempVar->ActiveBuffs = UpdatedBuffs;
                SendServerPacket(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            }
            RefreshAllStats();
        }
    }

    GuildBuff *<missing_class_definition>::GetBuff(int Id)
    {
        for (int i = 0; i < BuffList->Count; i++)
        {
            if (BuffList[i]->Id == Id)
            {
                return BuffList[i];
            }
        }
        return nullptr;
    }

    void <missing_class_definition>::NewBuff(int Id, bool charge)
    {
        GuildBuffInfo *Info = Envir::FindGuildBuffInfo(Id);
        if (Info == nullptr)
        {
            return;
        }
        GuildBuff *Buff = new GuildBuff();
        Buff->Id = Id;
        Buff->Info = Info;
        Buff->Active = true;
        Buff->ActiveTimeRemaining = Buff->Info->TimeLimit;

        if (charge)
        {
            ChargeForBuff(Buff);
        }

        BuffList->Add(Buff);
        std::vector<GuildBuff*> NewBuff = {Buff};
        ServerPackets::GuildBuffList *tempVar = new ServerPackets::GuildBuffList();
        tempVar->ActiveBuffs = NewBuff;
        SendServerPacket(tempVar);
        //now tell everyone our new sparepoints
        for (int i = 0; i < Ranks->Count; i++)
        {
            for (int j = 0; j < Ranks[i].Members->Count; j++)
            {
                if (Ranks[i].Members[j].Player != nullptr)
                {
                    SendGuildStatus(static_cast<PlayerObject*>(Ranks[i].Members[j].Player));
                }
            }
        }
        NeedSave = true;
        RefreshAllStats();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete Buff' statement was not added since Buff was passed to a method or constructor. Handle memory management manually.
    }

    void <missing_class_definition>::ChargeForBuff(GuildBuff *buff)
    {
        if (buff == nullptr)
        {
            return;
        }

        SparePoints -= buff->Info->PointsRequirement;
    }

    void <missing_class_definition>::ActivateBuff(int Id)
    {
        GuildBuff *Buff = GetBuff(Id);
        if (Buff == nullptr)
        {
            return;
        }
        if (Buff->Active)
        {
            return; //no point activating buffs if they have no time limit anyway
        }
        if (Gold < Buff->Info->ActivationCost)
        {
            return;
        }
        Buff->Active = true;
        Buff->ActiveTimeRemaining = Buff->Info->TimeLimit;
        Gold -= static_cast<unsigned int>(Buff->Info->ActivationCost);
        std::vector<GuildBuff*> NewBuff = {Buff};
        ServerPackets::GuildBuffList *tempVar = new ServerPackets::GuildBuffList();
        tempVar->ActiveBuffs = NewBuff;
        SendServerPacket(tempVar);
        ServerPackets::GuildStorageGoldChange *tempVar2 = new ServerPackets::GuildStorageGoldChange();
        tempVar2->Type = 2;
        tempVar2->Name = "";
        tempVar2->Amount = static_cast<unsigned int>(Buff->Info->ActivationCost);
        SendServerPacket(tempVar2);
        NeedSave = true;
        RefreshAllStats();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void <missing_class_definition>::RemoveAllBuffs()
    {
        //note this removes them all but doesnt reset the sparepoints!(should make some sort of 'refreshpoints' procedure for that
        ServerPackets::GuildBuffList *tempVar = new ServerPackets::GuildBuffList();
        tempVar->Remove = 1;
        tempVar->ActiveBuffs = BuffList;
        SendServerPacket(tempVar);
        BuffList->Clear();
        RefreshAllStats();
        NeedSave = true;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }
}

GuildAtWar::GuildAtWar(GuildObject *a, GuildObject *b)
{
    GuildA = a;
    GuildB = b;

    GuildA::WarringGuilds->Add(GuildB);
    GuildB::WarringGuilds->Add(GuildA);

    TimeRemaining = Settings::Minute * Settings::Guild_WarTime;
}

void GuildAtWar::EndWar()
{
    GuildA::WarringGuilds->Remove(GuildB);
    GuildB::WarringGuilds->Remove(GuildA);

    GuildA::SendMessage(StringHelper::formatSimple("War ended with {0}.", GuildB->Name), ChatType::Guild);
    GuildB::SendMessage(StringHelper::formatSimple("War ended with {0}.", GuildA->Name), ChatType::Guild);
    GuildA::UpdatePlayersColours();
    GuildB::UpdatePlayersColours();
}
